package oop.ex2.main;

import java.io.IOException;
import java.util.ArrayList;

import oop.ex2.tools.CheckType;
import oop.ex2.tools.ReadTextFile;
import oop.ex2.tools.TextProcessor;

/**
 * 
 * @author yossavi
 *
 */
public class Sjavac {
	public static String line;
	public static ReadTextFile commands;
	
	public static ArrayList<Variable> members = new ArrayList<Variable>();
	public static ArrayList<Block> methods = new ArrayList<Block>();
	public static ArrayList<String> variablesLines = new ArrayList<String>();
	
	/**
	 * run over the whole file, 
	 * checks if the code are valid by the "Simple Java" rules.
	 * after the check it's will exit the program and send status:
	 * (0) if the code is valid
	 * (1) if the code is invalid
	 * (2) if there was an IOException
	 * @param args - The path of the "Simple Java" file to compile
	 */
	public static void main(String[] args) {
		try {
			String javacFile=args[0];
			commands = new ReadTextFile(javacFile);
		
			nextLine ();
			while (line!=null) {
				TextProcessor.cleanCode();
				// if the cleanCode() already reach the end of the text
				if (Sjavac.line==null)
					break;
				// If the line is a variable declaration
				if (CheckType.isCommand(line)){
					// Saves as a string to handle later on
					variablesLines.add(TextProcessor.removeLast(line));
					nextLine();
					continue;
				}
				
				// If the line is a beginning of a method
				if (CheckType.isBlock(line)){
					// Saves the method declaration and is lines in "Block" object
					addUniqMethod (CorrectnessAndHandle.handleMethod(line), methods);
					continue;
				}
				
				throw new compilationException("UnKnown command: "+ line);
			}
			// Close stream
			commands.close ();
			
			// run over variable lines 
			for (String v: variablesLines) {
				// Saves the variable in members ArrayList as "Variable" object
				addUniqVar (CorrectnessAndHandle.handleVariable(v,false), members);
			}
			// run over the saved methods
			for (Block m: methods) {
				// saves the current method in helper variable
				CheckType.currentMethod=m;
				// Checks if the body of the method is correct
				m.checkCorrectness();
			}
		}
		catch (IOException e) {
			System.exit(2);
		}
		catch (compilationException e) {
			System.exit(1);
		}
		System.exit(0);
	}
	
	/**
	 * replace the member "line" with the next line from file
	 * @throws IOException
	 */
	public static void nextLine () throws IOException {
		line = commands.readLine();
		//System.out.println(line);
	}
	
	/**
	 * Checks if the variable isn't exist and add it to array of Variables
	 * if it does it will throw DuplicateNamesException
	 * @param variable- the variable to add
	 * @param varsArray- the ArrayList to add to
	 * @throws DuplicateNamesException 
	 */
	public static void addUniqVar (Variable variable, ArrayList<Variable> varsArray) throws DuplicateNamesException {
		for (Variable m: varsArray) {
			if (m.getName().equals(variable.getName()))
				throw new DuplicateNamesException("variable can't initial more than one time");
		}
		varsArray.add(variable);
	}
	
	/**
	 * Checks if the method isn't exist and add it to array of Blocks
	 * if it does it will throw DuplicateNamesException
	 * @param method- the method to add
	 * @param methosArray- the ArrayList to add to
	 * @throws DuplicateNamesException
	 */
	public static void addUniqMethod (Block method, ArrayList<Block> methosArray) throws DuplicateNamesException {
		for (Block m: methosArray) {
			if (m.getName().equals(method.getName()))
				throw new DuplicateNamesException("method can't initial more than one");
		}
		methosArray.add(method);
	}
}
